#include "janusclient.h"
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonValue>
#include <QJsonArray> // 需要包含 QJsonArray
#include <QDebug>
#include <QUuid> // 用于生成事务 ID

// Keepalive 间隔 (毫秒)，Janus 默认 Session 超时是 60 秒
const int KEEPALIVE_INTERVAL_MS = 30000; // 30 秒发送一次

JanusClient::JanusClient(QObject *parent)
    : QObject(parent),
    m_websocket(new CWebSocket(this)), // 创建 WebSocket 实例
    m_currentState(State::Disconnected),
    m_sessionId(-1),
    m_keepAliveTimer(new QTimer(this))
{
    // 连接 WebSocket 信号
    connect(m_websocket, &CWebSocket::connected, this, &JanusClient::onWebSocketConnected);
    connect(m_websocket, &CWebSocket::disconnected, this, &JanusClient::onWebSocketDisconnected);
    connect(m_websocket, &CWebSocket::textMessageReceived, this, &JanusClient::onWebSocketTextMessageReceived);
    connect(m_websocket, &CWebSocket::errorOccurred, this, &JanusClient::onWebSocketError);

    // 连接 Keepalive 定时器
    connect(m_keepAliveTimer, &QTimer::timeout, this, &JanusClient::onKeepAliveTimeout);
    m_keepAliveTimer->setInterval(KEEPALIVE_INTERVAL_MS);
}

JanusClient::~JanusClient()
{
    // 析构时确保断开连接并停止定时器
    disconnectFromServer();
    // m_websocket 和 m_keepAliveTimer 会因父对象关系自动删除
}

void JanusClient::connectToServer(const QUrl &url)
{
    if (m_currentState != State::Disconnected && m_currentState != State::Error) {
        qWarning() << "JanusClient::connectToServer: Already connected or connecting.";
        return;
    }

    m_serverUrl = url;
    m_sessionId = -1; // 重置 Session ID
    m_lastError.clear();
    m_pendingTransactions.clear(); // 清除旧事务

    setState(State::ConnectingWebSocket);
    m_websocket->connectToServer(m_serverUrl);
}

void JanusClient::disconnectFromServer()
{
    if (m_currentState == State::Disconnected) {
        return;
    }

    qInfo() << "JanusClient::disconnectFromServer: Disconnecting...";
    setState(State::Closing);
    stopKeepAliveTimer();

    if (m_sessionId != -1) {
        sendDestroySessionRequest(); // 尝试优雅销毁 Session
    }

    m_websocket->disconnectFromServer(); // 关闭 WebSocket
    m_sessionId = -1;
    // onWebSocketDisconnected 会最终将状态设置为 Disconnected
}

JanusClient::State JanusClient::getCurrentState() const
{
    return m_currentState;
}

long long JanusClient::getSessionId() const
{
    return m_sessionId;
}

QString JanusClient::getLastError() const
{
    return m_lastError;
}

// --- WebSocket 信号处理 ---

void JanusClient::onWebSocketConnected()
{
    if (m_currentState != State::ConnectingWebSocket) {
        qWarning() << "JanusClient::onWebSocketConnected: Received connected signal in unexpected state:" << m_currentState;
        // 可能需要处理重连逻辑或错误状态
        return;
    }
    qInfo() << "JanusClient: WebSocket connected. Creating session...";
    setState(State::WebSocketConnected);
    sendCreateSessionRequest(); // WebSocket 连接成功后，发送创建 Session 请求
}

void JanusClient::onWebSocketDisconnected()
{
    qInfo() << "JanusClient: WebSocket disconnected.";
    // 无论之前的状态如何，WebSocket 断开意味着彻底断开
    if (m_currentState != State::Disconnected) { // 避免重复发送信号
        m_lastError = "WebSocket connection closed.";
        stopKeepAliveTimer();
        m_sessionId = -1; // Session 也失效了
        setState(State::Disconnected); // 更新状态
        emit disconnected(); // 发出最终的断开信号
    }
    m_pendingTransactions.clear(); // 清除所有待处理事务
}

void JanusClient::onWebSocketError(const QString &errorString)
{
    qWarning() << "JanusClient: WebSocket error:" << errorString;
    m_lastError = "WebSocket Error: " + errorString;
    stopKeepAliveTimer();
    m_sessionId = -1;
    // 即使 WebSocket 错误，也可能先收到 disconnected 信号
    if (m_currentState != State::Disconnected) {
        setState(State::Error);
        emit errorOccurred(m_lastError);
        // 通常 WebSocket 错误后会触发 onWebSocketDisconnected，那里会设置最终状态
    }
    m_pendingTransactions.clear();
}

void JanusClient::onWebSocketTextMessageReceived(const QString &message)
{
    // qInfo() << "JanusClient: Received message:" << message;
    QJsonParseError parseError;
    QJsonDocument jsonDoc = QJsonDocument::fromJson(message.toUtf8(), &parseError);

    if (parseError.error != QJsonParseError::NoError) {
        qWarning() << "JanusClient: Failed to parse JSON message:" << parseError.errorString() << "Original message:" << message;
        // 可以选择性地发出错误信号
        // m_lastError = "JSON Parse Error: " + parseError.errorString();
        // emit errorOccurred(m_lastError);
        return;
    }

    if (!jsonDoc.isObject()) {
        qWarning() << "JanusClient: Received JSON is not an object:" << message;
        return;
    }

    handleJanusMessage(jsonDoc.object());
}

// --- Keepalive 处理 ---

void JanusClient::onKeepAliveTimeout()
{
    if (m_currentState == State::SessionActive && m_sessionId != -1) {
        // qInfo() << "JanusClient: Sending keepalive for session" << m_sessionId;
        sendKeepAliveRequest();
    } else {
        qWarning() << "JanusClient: Keepalive timeout occurred in non-active state:" << m_currentState;
        // 可能连接已丢失，停止定时器
        stopKeepAliveTimer();
    }
}

void JanusClient::startKeepAliveTimer()
{
    if (!m_keepAliveTimer->isActive()) {
        qInfo() << "JanusClient: Starting keepalive timer (interval: " << KEEPALIVE_INTERVAL_MS << "ms)";
        m_keepAliveTimer->start();
    }
}

void JanusClient::stopKeepAliveTimer()
{
    if (m_keepAliveTimer->isActive()) {
        qInfo() << "JanusClient: Stopping keepalive timer.";
        m_keepAliveTimer->stop();
    }
}

// --- 状态和消息发送/处理 ---

void JanusClient::setState(State newState)
{
    if (m_currentState != newState) {
        qInfo() << "JanusClient: State changed from" << m_currentState << "to" << newState;
        m_currentState = newState;
        emit stateChanged(m_currentState); // 发出状态变化信号
    }
}

QString JanusClient::generateTransactionId() const
{
    // 使用 QUuid 生成唯一的字符串 ID
    return QUuid::createUuid().toString(QUuid::WithoutBraces);
}

bool JanusClient::sendMessage(const QJsonObject &message,
                              const QString &transactionId,
                              long long handleId,
                              std::function<void (const QJsonObject &)> callback)
{
    if (m_currentState < State::WebSocketConnected || m_currentState == State::Error || m_currentState == State::Closing) {
        qWarning() << "JanusClient::sendMessage: Cannot send message in state" << m_currentState;
        return false;
    }
    if (!m_websocket->isConnected()) {
        qWarning() << "JanusClient::sendMessage: WebSocket is not connected.";
        return false;
    }


    QJsonObject fullMessage = message;
    QString tid = transactionId.isEmpty() ? generateTransactionId() : transactionId;
    fullMessage["transaction"] = tid;
    fullMessage["janus"] = message.value("janus").toString(); // 确保 janus 字段存在

    if (m_sessionId != -1 && !fullMessage.contains("session_id")) { // 自动添加 session_id (除非是 create 请求)
        if (fullMessage["janus"] != "create") {
            fullMessage["session_id"] = m_sessionId;
        }
    }
    if (handleId != -1 && !fullMessage.contains("handle_id")) { // 自动添加 handle_id
        fullMessage["handle_id"] = handleId;
    }

    QJsonDocument doc(fullMessage);
    QString messageString = QString::fromUtf8(doc.toJson(QJsonDocument::Compact));

    qInfo() << "JanusClient SEND:" << messageString; // 调试输出发送的消息

    if (callback && !tid.isEmpty()) {
        m_pendingTransactions[tid] = callback;
    }

    qint64 bytesSent = m_websocket->sendTextMessage(messageString);
    if (bytesSent <= 0) {
        qWarning() << "JanusClient::sendMessage: WebSocket sendTextMessage failed or sent 0 bytes.";
        if (callback && !tid.isEmpty()) {
            m_pendingTransactions.remove(tid); // 发送失败，移除回调
        }
        // 触发错误可能有点过激，取决于 WebSocket 内部是否已报告错误
        // m_lastError = "Failed to send message via WebSocket.";
        // emit errorOccurred(m_lastError);
        // setState(State::Error);
        return false;
    }

    return true;
}

void JanusClient::handleJanusMessage(const QJsonObject &jsonObject)
{
    QString type = jsonObject.value("janus").toString();
    QString transaction = jsonObject.value("transaction").toString();
    long long senderHandleId = jsonObject.value("sender").toVariant().toLongLong(); // 事件的发送者句柄

    qInfo() << "JanusClient RECV:" << QJsonDocument(jsonObject).toJson(QJsonDocument::Compact); // 调试输出接收的消息

    // 检查是否有匹配的事务回调
    if (!transaction.isEmpty() && m_pendingTransactions.contains(transaction)) {
        auto callback = m_pendingTransactions.take(transaction); // 获取并移除回调
        if (callback) {
            // 不论是 success, error 还是 ack，都调用回调
            callback(jsonObject);
            // 如果是 ack，我们可能还想继续处理下面的通用逻辑 (例如启动 keepalive)
            // 如果是 error 或 success，则通常不需要进一步的通用处理
            if (type != "ack") {
                // 对于 error，通用错误处理逻辑在下面也会捕捉到
                // 对于 success，如果回调处理了所有事情，可以提前返回
                // return; // 根据需要决定是否在这里返回
            }
        }
    }

    // --- 通用消息类型处理 ---
    if (type == "success") {
        if (m_currentState == State::CreatingSession) {
            // 这是创建 Session 的响应
            m_sessionId = jsonObject.value("data").toObject().value("id").toVariant().toLongLong();
            if (m_sessionId > 0) {
                qInfo() << "JanusClient: Session created successfully, ID:" << m_sessionId;
                setState(State::SessionActive);
                startKeepAliveTimer(); // Session 激活后启动 Keepalive
                emit sessionCreated(m_sessionId);
            } else {
                qWarning() << "JanusClient: Received success for session creation, but ID is invalid:" << jsonObject;
                m_lastError = "Failed to create session: Invalid ID received.";
                setState(State::Error);
                emit errorOccurred(m_lastError);
                disconnectFromServer(); // 创建失败，断开连接
            }
        } else {
            // 其他 success 消息通常由事务回调处理，或者如果没回调就忽略
            qDebug() << "JanusClient: Received generic 'success' message (might be handled by transaction):" << transaction;
        }

    } else if (type == "error") {
        QJsonObject errorObj = jsonObject.value("error").toObject();
        int code = errorObj.value("code").toInt();
        QString reason = errorObj.value("reason").toString();
        qWarning() << "JanusClient: Received Janus error:" << code << reason;
        m_lastError = QString("Janus Error (%1): %2").arg(code).arg(reason);

        if (m_currentState == State::CreatingSession) {
            setState(State::Error);
            emit errorOccurred(m_lastError); // 发出错误信号
            disconnectFromServer(); // 创建 Session 失败，断开连接
        } else {
            // 其他错误可能与 Handle 相关，先发出信号
            emit errorOccurred(m_lastError);
            // 可以考虑是否需要根据错误码改变状态或断开连接
            // 例如，458 (Session not found) 或 459 (Handle not found) 可能意味着需要重置
            if (code == 458 || code == 459) {
                // 可能需要更复杂的处理，例如尝试重新创建 Session 或通知上层
                // disconnectFromServer(); // 简单的处理是直接断开
            }
            // 其他错误可能只是某个操作失败，不一定需要断开
        }

    } else if (type == "ack") {
        // 通常表示请求已被 Janus 服务器接收，可以忽略，或者由事务回调处理
        qDebug() << "JanusClient: Received 'ack' for transaction:" << transaction;

    } else if (type == "keepalive") {
        // 收到服务器的 keepalive 响应（理论上 Janus 不会主动发，这是我们自己请求的响应）
        // 通常是 success 类型，这里不需要特别处理
        qDebug() << "JanusClient: Received 'keepalive' response.";


    } else if (type == "event") {
        if (senderHandleId <= 0) {
            qWarning() << "JanusClient: Received event without valid sender handle ID:" << jsonObject;
            return;
        }

        QJsonObject plugindata = jsonObject.value("plugindata").toObject();
        if (plugindata.isEmpty()) {
            qWarning() << "JanusClient: Received event without plugindata:" << jsonObject;
            return;
        }
        QJsonObject data = plugindata.value("data").toObject();
        QJsonObject jsep = jsonObject.value("jsep").toObject();

        // 检查是否有 JSEP (SDP Offer/Answer)
        if (!jsep.isEmpty()) {
            emit jsepReceived(senderHandleId, jsep);
        }

        // 调用纯虚方法（通过信号转发）让子类处理事件的具体内容
        emit janusEventReceived(senderHandleId, data); // 发送 "data" 部分
        emit janusPluginDataReceived(senderHandleId, plugindata); // 发送整个 "plugindata"

    } else if (type == "webrtcup") {
        // PeerConnection 建立成功
        qInfo() << "JanusClient: WebRTC connection is UP for handle:" << senderHandleId;
        // 子类可能需要处理这个状态

    } else if (type == "hangup") {
        // PeerConnection 关闭
        qWarning() << "JanusClient: WebRTC connection HANGUP for handle:" << senderHandleId
                   << "Reason:" << jsonObject.value("reason").toString();
        // 子类需要处理这个事件，例如清理资源

    } else if (type == "detached") {
        // Handle 已被销毁
        qInfo() << "JanusClient: Handle DETACHED:" << senderHandleId;
        // 子类需要清理与此 Handle 相关的资源

    } else if (type == "media") {
        // 媒体流状态变化 (receiving/sending true/false)
        qInfo() << "JanusClient: Media status changed for handle:" << senderHandleId << jsonObject;
        // 子类可能需要根据媒体状态更新 UI 或逻辑

    } else if (type == "slowlink") {
        // 网络状况不佳
        qWarning() << "JanusClient: Slow link detected for handle:" << senderHandleId << jsonObject;
        // 可以通知用户或尝试降低码率

    } else {
        qWarning() << "JanusClient: Received unknown Janus message type:" << type << jsonObject;
    }
}

// --- 私有请求发送方法 ---

void JanusClient::sendCreateSessionRequest()
{
    if (m_currentState != State::WebSocketConnected) return;

    setState(State::CreatingSession);
    QJsonObject request;
    request["janus"] = "create";
    // 使用 sendMessage 发送，不需要手动加 transaction，它会自动生成
    sendMessage(request);
    // Session 创建的响应会在 handleJanusMessage 中处理
}

void JanusClient::sendDestroySessionRequest()
{
    if (m_sessionId == -1) return;

    qInfo() << "JanusClient: Sending destroy session request for ID:" << m_sessionId;
    QJsonObject request;
    request["janus"] = "destroy";
    // 这里发送不需要回调，因为我们正在关闭
    sendMessage(request);
    m_sessionId = -1; // 立即标记 Session ID 无效
}

void JanusClient::sendKeepAliveRequest()
{
    if (m_sessionId == -1 || m_currentState != State::SessionActive) return;

    QJsonObject request;
    request["janus"] = "keepalive";
    // 使用 sendMessage 发送，不需要回调，响应会在 handleJanusMessage 中处理 (通常是 success)
    sendMessage(request);
}
